#pragma once

#include <AVUIGeneralTransform.h>
#include <AVUIMatrix3D.h>
#include <AVUIRect3D.h>

// REVIEW ALL Animatable/Freezables!
namespace AVUI {

class GeneralTransform3DTo2D;
class GeneralTransform2DTo3D;
class MeshGeometry3D;
class Camera;

class GeneralTransform2DTo3DTo2D : public GeneralTransform
{
public:
    DECLARE_ELEMENT(GeneralTransform2DTo3DTo2D, GeneralTransform);
    GeneralTransform2DTo3DTo2D() { };
    GeneralTransform2DTo3DTo2D(Viewport2DVisual3D* pVisual3D, Visual* pFromVisual);

    virtual Rect TransformBounds(Rect rect) AVUI_OVERRIDE;
    virtual bool TryTransform(const Point& inPoint, Point* pResult) AVUI_OVERRIDE;

	virtual TRefCountedPtr<AVUI::Transform> get_AffineTransform() AVUI_OVERRIDE { return NULL; }
    virtual TRefCountedPtr<GeneralTransform> get_Inverse();

    bool get_IsInverse() { return m_fInverse; }
    void set_IsInverse(bool isInverse) { m_fInverse = isInverse; }

protected:

    virtual TRefCountedPtr<Freezable> CreateInstanceCore() AVUI_OVERRIDE { return object_allocate<GeneralTransform2DTo3DTo2D>().get_Ptr(); }
    virtual void CloneCore(Freezable* pSource) AVUI_OVERRIDE;

private:
    void CopyCommon(GeneralTransform2DTo3DTo2D* pTransform);

    bool TryRegularTransform(const Point& inPoint, Point* pResult);
    bool TryInverseTransform(const Point& inPoint, Point* pResult);
    void InverseTransformHitTestResult(Object* pSender, HitTestResultArgs* pRawResult);
 

    Rect3D m_boundingRect;
    TRefCountedPtr<Camera> m_pCamera;
    bool m_fInverse;
    TRefCountedPtr<MeshGeometry3D> m_pGeometry;
    TRefCountedPtr<GeneralTransform3DTo2D> m_pObjectToViewport;
    TRefCountedPtr<GeneralTransform> m_pTransform2D;
    TRefCountedPtr<GeneralTransform> m_pTransform2DInverse;
    Size m_viewSize;
    Rect m_visualBounds;
    Rect m_visualBrushBounds;
    Matrix3D m_worldTransformation;

    bool m_foundIntersection;
    Point m_pointHit;
};


}; // namespace AVUI
